|
Q We need a handle to a pop-up menu in a
dialog so that we can dynamically change its items. I tried to set
the menu ID to -12345 and stuff a dynamically allocated menu handle
into the pop-up control's "private" data field, but this menu does
not appear. Please advise. I have also had problems with disposing a
dialog which contains a pop-up menu control if there are other
instances of the same dialog, because disposing the first dialog
disposes the menu handle, and the other dialogs can no longer use it.
I've attempted (without success) to circumvent this by NULLing the
menu reference in the control prior to disposing the dialog. Does the
control create another reference to the menu I am unable to get at?
Is there any way around this issue? Basically, how do I retain my
reference to my menu after closing the window?
P.S. I need solutions
that work regardless of whether the Appearance extension is
installed.
A Your question reads as if you are having a
number of problems. Fortunately, there is only one. Here is some
little-known wisdom regarding the pop-up menu CDEFs (both
popupMenuProc and kControlPopupButtonProc):
|
What should you do instead?
NewMenu
or GetMenu
.InsertMenu
. (Remember to pass
hierMenu
in the second
parameter, since pop-up menus go into the "hierarchical" portion
of the menu list. Don't think too hard about this terminology or
you'll embarrass whoever invented it.)GetNewDialog
,
NewDialog
,
GetNewControl
, or
NewControl
.ModalDialog
or
DialogSelect
or
TrackControl
or
HandleControlClick
. Repopulate
the menu as you please, but remember to reset the control's
maximum setting if you change the number of items in the menu, and
redraw the control (invalidate it or call
Draw1Control
) if you change
the menu item which represents the current value.DisposeDialog
or
DisposeControl
.DeleteMenu
.DisposeMenu
.How and why does this help? The pop-up menu CDEFs look in two places for the menu you specify.
GetMenuHandle
. If they find a
menu this way, they behave rationally and predictably: they assume
you will be responsible for deleting and disposing the menu. Thus,
the menu will persist after the control is disposed and multiple
instances of the control will not cause you trouble. The other
advantage is that you already have the menu handle, so there is no
need to go poking through obscure data hanging off the control
record.GetMenu
to find
and load a 'MENU' resource. They insert and delete the resulting
menu into and from the menu list as necessary, and they dispose
the menu when the control is disposed. (They also go to great
lengths to allow the menu to be purged at certain times, which can
cause headaches which are beyond the scope of this document.)We recommend you always make sure the CDEFs can find the menus they want in the menu list by using the numbered steps listed above. If you don't follow these steps, the CDEFs will create and manage the menus, the problems you describe will crop up, and things will get tedious very quickly. The only time you want to allow the CDEFs to create a menu is when you know the menu will only be used in a single (optimally moveable) modal dialog. If you'd rather not keep this exception in mind, just follow the numbered steps; they always work.
By the way, yes, the CDEFs do cache a reference to the menu in a place other than their "private" control data, so changing that data will not help. In fact, altering system data structures is a good thing to avoid in general. Read when you must, but don't ever write if you can possibly avoid it. Also, take a look at what the Mac OS 8 Control Manager has to say about the Pop-Up Menu Private Structure(PopupPrivateData). Executive summary: Use the accessor functions, Luke!
Thanks to: Matt Ackeret, Guy Fullerton, and Quinn "The Eskimo!"
Technical Q&As
Previous Question | Contents | Next Question
To contact us, please use the Contact
Us page.